Skip to content

feat(triggers): first real SKILL_OBSERVATION_TRIGGER — clipboard URL → web_fetch#14

Merged
AVADSA25 merged 1 commit into
mainfrom
feat/clipboard-url-trigger
May 3, 2026
Merged

feat(triggers): first real SKILL_OBSERVATION_TRIGGER — clipboard URL → web_fetch#14
AVADSA25 merged 1 commit into
mainfrom
feat/clipboard-url-trigger

Conversation

@AVADSA25
Copy link
Copy Markdown
Owner

@AVADSA25 AVADSA25 commented May 2, 2026

Summary

First real declarative SKILL_OBSERVATION_TRIGGER shipped after Phase 2 Step 6. Until now, trigger_fired / trigger_blocked events were dormant in production because zero installed skills declared the constant. This PR proves Step 6 end-to-end.

What this ships

Skill: clipboard_url_fetch — auto-fetches HTTP/HTTPS URLs copied to clipboard, with a consent prompt before any network call.

Trigger field Value
type clipboard_pattern
pattern r"https?://[^\s<>'\"]+"
cooldown_seconds 600 (10 min per (skill, trigger) key)
require_confirmation True → routes through codec_ask_user.ask
destructive False → no strict-consent verb-match needed
Stable key clipboard_url_fetch:07734ae8

Runtime flow

  1. codec_observer.poll() captures snapshot["clipboard"]["preview"]
  2. codec_triggers.evaluate(snapshot) matches the regex → emits trigger_evaluated
  3. _await_confirmation posts ask_user notification: "Fetch and summarize this URL?"
  4. User confirms in PWA / voice → _dispatchcodec_dispatch.run_skill("clipboard_url_fetch", ...)
  5. Skill reads pbpaste at runtime (handles clipboard changes between trigger fire and skill execution), delegates to existing web_fetch.run(url), returns content truncated to 2000 chars
  6. Audit emit: trigger_fired (paired with the earlier trigger_evaluated)

Manual paths (chat / voice / MCP) work too via SKILL_TRIGGERS = ["fetch clipboard url", "summarize clipboard", ...].

Files

File Lines What
skills/clipboard_url_fetch.py NEW (~140) Skill implementation + trigger declaration
tests/test_clipboard_url_fetch.py NEW (~190, 15 tests) metadata, schema validation, pattern semantics, URL extraction, run() behaviors
codec_dashboard.py +3 Add clipboard_url_fetch to CHAT_SKILL_ALLOWLIST (same gotcha lesson as PR #13)

Test plan

  • 🧪 RUNNING PYTEST NOW — tests/test_clipboard_url_fetch.py → 15 passed
  • 🧪 Full suite — 839 passed / 20 failed / 73 skipped (same 20/73 baseline as main, +15 from new tests)
  • AST discovery via codec_triggers.discover_triggers(SkillRegistry) → 1 trigger found (was 0 on main)
  • Post-merge: git pull && cp skills/clipboard_url_fetch.py ~/.codec/skills/ && pm2 restart codec-observer codec-dashboard
  • Real-world test: copy a URL (e.g. https://news.ycombinator.com), wait for ask_user notification, confirm, expect notification with fetched content

Why this trigger first

Considered options — chrome_open on Slack window-title (low risk, niche use), bitcoin_price on BTC clipboard (forex/crypto trader use case but narrow), URL → web_fetch (universally useful, bounded privacy via consent gate). Picked URL because it exercises the most parts of the Step 6 plumbing: clipboard matcher + cooldown + require_confirmation gate + delegate-to-existing-skill pattern.

🤖 Generated with Claude Code

…→ web_fetch

Phase 2 Step 6 shipped the trigger system but no skill declared a
SKILL_OBSERVATION_TRIGGER constant, so trigger_fired/blocked audit
events stayed dormant in production. This PR ships the first real
declarative trigger to prove Step 6 end-to-end.

Skill: clipboard_url_fetch
  - Trigger type: clipboard_pattern
  - Pattern: r"https?://[^\s<>'\"]+"
  - Cooldown: 600s (10 min) per (skill, trigger) key
  - require_confirmation: True → routes through codec_ask_user.ask
  - destructive: False → no strict-consent verb-match needed
  - Stable key: clipboard_url_fetch:07734ae8

Runtime:
  - Trigger fires on observation_tick when clipboard preview matches
  - User sees ask_user prompt: "Fetch and summarize this URL?"
  - On approval: skill reads pbpaste at runtime, delegates to
    web_fetch.run(url), returns content truncated to 2000 chars
  - On reject / timeout: codec_triggers emits trigger_blocked

Manual paths (chat / voice / MCP) work too via SKILL_TRIGGERS list:
"fetch clipboard url", "summarize clipboard", etc.

Tests: 15 new tests in tests/test_clipboard_url_fetch.py covering
metadata correctness (incl. CHAT_SKILL_ALLOWLIST regression — same
gotcha as PR #13), trigger schema validation against
codec_triggers._validate_trigger_dict, pattern semantics, URL
extraction, and 5 run() behaviors. All mock subprocess + web_fetch
— never makes a real network call, never reads the user's clipboard.

Full suite: 839 passed / 20 failed / 73 skipped — same 20/73 baseline
as main, +15 from new tests.

Verified via direct invocation of
codec_triggers.discover_triggers(SkillRegistry) → 1 trigger found
(was 0 on main).

Deploy:
  git pull && cp skills/clipboard_url_fetch.py ~/.codec/skills/
  pm2 restart codec-observer codec-dashboard
@AVADSA25 AVADSA25 merged commit 7e4b021 into main May 3, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants